/**
 * 最基础版本的深拷贝
 * 使用递归的思想
 * 考虑了数组的情况
 * 解决循环引用的问题
 * WeekMap优化：target和obj之间存在弱引用关系，下一次垃圾回收机制执行的时候，内存空间会被回收
 * 缺点：
 * 只考虑了基本类型、object和Array，没有考虑函数、正则、symbol
 * */ 
/**
 * 
 * @param {*} array 执行的数组
 * @param {*} iteratee 迭代数组时，执行的方法
 */
function forEach(array, iteratee) {
  let index = -1
  let length = array.length
  while(++index < length) {
    iteratee(array[index],index)
  }
  return array
}

/**
 * 深拷贝方法1
 * @param {*} target 
 * @param {*} map 
 */
function clone1 (target, map = new WeakMap()) {
  if (typeof target === 'object') {
    let isArray = Array.isArray(target)
    let cloneTarget = isArray ? [] : {};
    if (map.get(target)) {
      return map.get(target)
    }
    map.set(target, cloneTarget)
    for (key in target) {
      cloneTarget[key] = clone1(target[key], map)
    }
    return cloneTarget
  } else {
    return target
  }
}

/**
 * 深拷贝 方法2
 * @param {*} target 
 * @param {*} map 
 */
function clone2 (target, map = new WeakMap()) {
  if (typeof target === 'object') {
    let isArray = Array.isArray(target)
    let cloneTarget = isArray ? [] : {};
    if (map.get(target)) {
      return map.get(target)
    }
    map.set(target, cloneTarget)
    const keys = isArray ? undefined : Object.keys(target)
    forEach(keys || target, (value, key) => {
      if (keys) {
        key = value
      }
      cloneTarget[key] = clone2(target[key], map)
    })
    return cloneTarget
  } else {
    return target
  }
}

const target = {
  field1: 1,
  field2: undefined,
  field3: {
      child: 'child'
  },
  field4: [2, 4, 8],
  f: { f: { f: { f: { f: { f: { f: { f: { f: { f: { f: { f: {} } } } } } } } } } } },
};

console.time()
const result = clone1(target)
console.timeEnd()

console.time() // 优化后时间明显减小
const result2 = clone2(target)
console.timeEnd()